package com.gsi.webstore.platform.storefront.pipelet.orderprocess;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.gsi.webstore.platform.adapter.storelocator.internal.client.data.Storefront;
import com.gsi.webstore.platform.component.shipping.capi.fulfillment.FulfillmentMethodManager;
import com.gsi.webstore.platform.storefront.capi.shipping.GSIShippingBucketBO;

import com.intershop.beehive.core.capi.domain.Domain;
import com.intershop.beehive.core.capi.naming.NamingMgr;
import com.intershop.beehive.core.capi.pipeline.Pipelet;
import com.intershop.beehive.core.capi.pipeline.PipeletExecutionException;
import com.intershop.beehive.core.capi.pipeline.PipelineDictionary;
import com.intershop.beehive.core.capi.pipeline.PipelineInitializationException;
import com.intershop.sellside.appbase.b2c.capi.order.ProductLineItemBO;

/**
 * 
 */
public class GetFulfillmentMethodsPerShippingBucket extends Pipelet
{

    /**
     * Constant used to access the pipeline dictionary with key 'ShippingBucketSet'
     */
    public static final String DN_SHIPPING_BUCKET_SET = "ShippingBucketSet";
    
    /**
     * Constant used to access the pipeline dictionary with key 'CurrentDomain'
     */
    public static final String DN_CURRENT_DOMAIN = "CurrentDomain";
    
    /**
     * Constant used to access the pipeline dictionary with key 'StoreFrontWithLineItemMap'
     */
    public static final String DN_STORE_FRONT_WITH_LINE_ITEM_MAP = "StoreFrontWithLineItemMap";
    
    /**
     * Constant used to access the pipeline dictionary with key 'FulfillmentMethodByShippingBucketMap'
     */
    public static final String DN_FULFILLMENT_METHOD_BY_SHIPPING_BUCKET_MAP = "FulfillmentMethodByShippingBucketMap";
    
    /**
     * Constant used to access the pipeline dictionary with key 'StorefrontByShippingBucketMap'
     */
    public static final String DN_STOREFRONT_BY_SHIPPING_BUCKET_MAP = "StorefrontByShippingBucketMap";

    /**
     * The pipelet's execute method is called whenever the pipelets gets
     * executed in the context of a pipeline and a request. The pipeline
     * dictionary valid for the currently executing thread is provided as a
     * parameter.
     * 
     * @param dict
     *            The pipeline dictionary to be used.
     * @throws PipeletExecutionException
     *             Thrown in case of severe errors that make the pipelet execute
     *             impossible (e.g. missing required input data).
     */
    public int execute(PipelineDictionary dict)throws PipeletExecutionException
    {        
        // lookup 'StoreFrontWithLineItemMap' in pipeline dictionary
        Map<String, Storefront> storeFrontWithLineItemMap = (Map)dict.get(DN_STORE_FRONT_WITH_LINE_ITEM_MAP);
        if (null == storeFrontWithLineItemMap)
        {
            throw new PipeletExecutionException(
                            "Mandatory input parameter 'StoreFrontWithLineItemMap' not available in pipeline dictionary.");
        }
        
        // lookup 'CurrentDomain' in pipeline dictionary
        Domain currentDomain = (Domain)dict.get(DN_CURRENT_DOMAIN);
        if (null == currentDomain)
        {
            throw new PipeletExecutionException("Mandatory input parameter 'CurrentDomain' not available in pipeline dictionary.");
        }

        // lookup 'ShippingBucketSet' in pipeline dictionary
        Set<GSIShippingBucketBO> shippingBucketSet = (Set)dict.get(DN_SHIPPING_BUCKET_SET);
        if (null == shippingBucketSet)
        {
            throw new PipeletExecutionException("Mandatory input parameter 'ShippingBucketSet' not available in pipeline dictionary.");
        }
        
        Map<String, String> fulfillmentMethodByBucketMap = new HashMap<String, String>();
        Map<String, Storefront> bucketStorefrontMap = new HashMap<String, Storefront>();
        
        for(GSIShippingBucketBO bucket : shippingBucketSet) 
        {
            String shipId = bucket.getSelectedShippingMethod().getId();
            
            String fulfillmentMethod = fulfillmentMethodMgr.getFulfillmentMethodFromShippingMethod(
                            shipId, currentDomain);
            String bucketId = bucket.getId();
            fulfillmentMethodByBucketMap.put(bucketId, fulfillmentMethod);
            
            /**
             * All lineitems in this shipping bucket are expected to have the
             * same storefront, but check all lineitems anyway and put whatever
             * non-null storefront is found into the Map.
             */
            for (ProductLineItemBO pli : bucket.getProductLineItemBOs()) 
            {
                Storefront storefront = (Storefront) storeFrontWithLineItemMap.get(pli.getID());
                
                if (storefront != null) 
                {
                    bucketStorefrontMap.put(bucketId, storefront);
                }
            }
        }
        // store 'FulfillmentMethodByShippingBucketMap' in pipeline dictionary
        dict.put(DN_FULFILLMENT_METHOD_BY_SHIPPING_BUCKET_MAP, fulfillmentMethodByBucketMap);
        
        // store 'StorefrontByShippingBucketMap' in pipeline dictionary
        dict.put(DN_STOREFRONT_BY_SHIPPING_BUCKET_MAP, bucketStorefrontMap);
        
        return PIPELET_NEXT;
    }
    
    public void init()
        throws PipelineInitializationException 
    {
        fulfillmentMethodMgr = (FulfillmentMethodManager)NamingMgr.getManager(FulfillmentMethodManager.class);
    }
    
    private FulfillmentMethodManager fulfillmentMethodMgr = null;
}